package com.zimi.core.security;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.zimi.bean.Constants;
import com.zimi.core.bean.UserConstantInterface;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("SpringJavaAutowiringInspection")
@Component
public class AuthenticationFilter extends OncePerRequestFilter {


    static boolean isAppRequest;

    /**
     * Same contract as for {@code doFilter}, but guaranteed to be
     * just invoked once per request within a single request thread.
     * See {@link #shouldNotFilterAsyncDispatch()} for details.
     * <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
     * default ServletRequest and ServletResponse ones.
     *
     * @param request
     * @param response
     * @param filterChain
     */
    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        if (StringUtils.equals("/login", request.getRequestURI())
                && StringUtils.equalsIgnoreCase(request.getMethod(), "POST")) {
            try {
                validate(new ServletWebRequest(request));
            } catch (BadCredentialsException e) {
                throw new BadCredentialsException("登录校验失败,请核对资料和附加信息");
            }
        }
        // 不是一个登录请求，不做校验 直接通过
        filterChain.doFilter(request, response);
    }

    private void validate(ServletWebRequest request) throws ServletRequestBindingException {
        HttpSession session = request.getRequest().getSession();
        String code = ServletRequestUtils.getStringParameter(request.getRequest(), "code");
        String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "captcha");
        String codeInSession = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
        isAppRequest=false;
        if (!StringUtils.isBlank(code)) {
            session.setAttribute(Constants.APP_USER_INFO, getOpenID(code));
        }
        if (!isAppRequest) {
            if (StringUtils.isBlank(codeInRequest))
                throw new BadCredentialsException("验证码不能为空！");
            if (!StringUtils.equals(codeInSession.toLowerCase(), codeInRequest.toLowerCase()))
                throw new BadCredentialsException("验证码不匹配");
            session.removeAttribute(Constants.KAPTCHA_SESSION_KEY);
        }
    }

    private Map<String, Object> getOpenID(String code) {
        Map<String, Object> param = new HashMap<>();
        param.put("appid", UserConstantInterface.WX_LOGIN_APPID);
        param.put("secret", UserConstantInterface.WX_LOGIN_SECRET);
        param.put("js_code", code);
        param.put("grant_type", UserConstantInterface.WX_LOGIN_GRANT_TYPE);
        String wxResult = HttpUtil.get(UserConstantInterface.WX_LOGIN_URL, param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        Map<String, Object> result = new HashMap<>();
        String session_key =  jsonObject.get("session_key").toString();
        String open_id =  jsonObject.get("openid").toString();
        result.put("session_key", session_key);
        result.put("open_id", open_id);
        isAppRequest=true;
        return result;
    }
}
